#include <sys/syscall.h>
#include <mips/regdef.h>

.data
char_in: .space 2		# espacio de memoria para alojar el byte de lectura mas el byte null
ASCII_0: .ascii	"0"		# caracter 0 para ser comparado con la entrada del usuario
ASCII_1: .ascii "1"		# caracter 1 para ser comparado con la entrada del usuario

	.text
	.align	2
	.globl	main
	.ent	main
# valores definidos para el OFFSET de las variables guardadas en el stack, 
# mas los codigos de retorno.

#define	MAIN_SF_SIZE	48
#define	MAIN_RA		40
#define	MAIN_FP		36
#define	MAIN_GP		32
#define	RETURN_VALUE	16
#define INPUT_CHAR	20
#define	POTENCIA	24
#define	ITERATOR	28

#define SYSERROR	2
#define	SUCCEEDED	0


main:
	.frame	$fp, MAIN_SF_SIZE, ra		
	.set	noreorder			
	.cpload	t9
	.set	reorder
	subu	sp, sp, MAIN_SF_SIZE
	
	sw	ra, MAIN_RA(sp)			# guardo los valores de registro de stack
	sw	$fp, MAIN_FP(sp)		# gp=32; fp=36; ra=40; align=44;
	sw	gp, MAIN_GP(sp)			# return_value=16; input_char=20; potencia=24; i=28
	move	$fp, sp
	sw	zero, INPUT_CHAR($fp) 	# input_char = 0
	
# itero leyendo cada caracter por stdin e imprimo su representacion
# en binario por stdout

while_char:
	li	a0, 0			# leo los bits desde stdin
	la	a1, char_in		# guardo el char leido en la direccion de char_in
	li	a2, 1
	li	v0, SYS_read	
	syscall
	bne	a3, zero, sys_error	# hubo un error al leer, termino el programa
	beq	v0, zero, success	# lei EOF, termino el programa
	lbu	t0, char_in			# guardo el byte char en el stack
	sw	t0, INPUT_CHAR($fp)
	sw	zero, ITERATOR($fp) # i= 0

for_condition:
	lw	t0, ITERATOR($fp)	# chequeo valor de i<8
	li 	t1, 7
	blt	t1, t0, while_char	# i>7, termina el for
for:
	li	t2, 7				# evaluo el char de entrada e imprimo cada bit del byte
	lw	t0, ITERATOR($fp)
	subu	t1, t2, t0 		# 7 - i
	li	t3, 1				# t3 = 1 
	sll	t3, t3, t1 			# potencia = 1 << (7-i)
	sw	t3, POTENCIA($fp)  	# guardo potencia
	lw	t0, INPUT_CHAR($fp) # t0 = codigo ascii de char entrada

	sub	t3, t0, t3   		# char_ascii >= potencia? bit 1 : bit 0
	blt	t3, zero, else_bit0 

	sw	t3, INPUT_CHAR($fp)		# guardo el remanente de input_char para el siguiente bit
	li	a0, 1					
	la	a1, ASCII_1				# el bit es un '1'. Lo imprimo
	li	a2, 1
	li	v0, SYS_write
	syscall
	bne	a3, zero, sys_error		# evaluo por error de escritura
	b	for_increment
	
else_bit0:
	li	a0, 1					
	la	a1, ASCII_0				# el bit es un '0'. Lo imprimo
	li	a2, 1
	li	v0, SYS_write
	syscall
	bne	a3, zero, sys_error		# evaluo por error de escritura

for_increment:
	lw	t2, ITERATOR($fp)		# incremento i para definir el siguiente bit
	addu	t2, t2, 1 
	sw	t2, ITERATOR($fp)
	b	for_condition

sys_error:
	li	t0, SYSERROR			# se produjo un error al llamar al syscall.
	sw	t0, RETURN_VALUE($fp)	# devuelvo codigo de error 2 como valor de retorno
	b end

success:
	li	t0, SUCCEEDED			# devuelvo 0 como codigo de retorno
	sw	t0, RETURN_VALUE($fp)
end:
	lw	v0, RETURN_VALUE($fp)		# cargo valor de retorno y los punteros del stack para la funcion madre
	move	sp, $fp
	lw	ra, MAIN_RA(sp)
	lw	$fp,MAIN_FP(sp)
	lw	gp,MAIN_GP(sp)
	addu	sp, sp, MAIN_SF_SIZE
	j	ra
	.end	main
